home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / drdobbs / 1991 / 10 / xalloc.asc < prev   
Text File  |  1991-09-10  |  8KB  |  354 lines

  1. _XALLOC: AN EXPANDED MEMORY MANAGER FOR TURBO PASCAL_
  2. by Herbert Gintis
  3.  
  4. [LISTING ONE]
  5.  
  6. unit xlineobj;
  7.  
  8. { Typical use:
  9.         program xtest;
  10.         uses xalloc,xlineobj;
  11.         var
  12.             s : xline;
  13.         begin
  14.             if not xalloc_init then halt;
  15.             s.init;
  16.             s.put_text('This goes into expanded memory');
  17.             writeln(s.get_text);
  18.             s.done;
  19.             xalloc_done;
  20.         end.
  21. }
  22. interface
  23.  
  24. uses xalloc;
  25.  
  26. type
  27.     xline = object
  28.         len : byte;
  29.         mem : xaddress;
  30.         constructor init;
  31.         destructor done; virtual;
  32.         procedure newsize(ncols : integer);
  33.         function get_text : string;
  34.         procedure put_text(s : string);
  35.     end;
  36.  
  37. implementation
  38.  
  39. var
  40.     xs : ^string;
  41.  
  42. constructor xline.init;
  43. const
  44.     mincols = 8;
  45. begin
  46.     xgetmem(mem,mincols);
  47.     len := mincols-1;
  48.     xs := xpage_in(mem);
  49.     xs^ := '';
  50. end;
  51.  
  52. destructor xline.done;
  53. begin
  54.     xfreemem(mem,len+1);
  55. end;
  56.  
  57. procedure xline.newsize(ncols : integer);
  58. begin
  59.     xfreemem(mem,len+1);
  60.     xgetmem(mem,ncols+1);
  61.     xs := xpage_in(mem);
  62.     len := ncols;
  63. end;
  64.  
  65. function xline.get_text : string;
  66. begin
  67.     xs := xpage_in(mem);
  68.     get_text := xs^;
  69. end;
  70.  
  71. procedure xline.put_text(s : string);
  72. begin
  73.     if length(s) <> len then newsize(length(s));
  74.     xs := xpage_in(mem);
  75.     xs^ := s;
  76. end;
  77.  
  78. end.
  79.  
  80.  
  81.  
  82.  
  83. [LISTING TWO]
  84.  
  85. unit xalloc;
  86.     {-See the unit xlineobj.pas for typical use of this unit}
  87. interface
  88.  
  89. const
  90.     nilpage = $ff;
  91. type
  92.     xaddress = record
  93.         page : byte;
  94.         pos : word;
  95.     end;
  96. function xalloc_init : boolean;
  97. procedure xgetmem(var x : xaddress;size : word);
  98. procedure xfreemem(var x : xaddress;size : word);
  99. function xpage_in(var x : xaddress) : pointer;
  100. function xmaxavail : longint;
  101. function xmemavail : longint;
  102. procedure xalloc_done;
  103.  
  104. implementation
  105.  
  106. uses crt,dos;
  107.  
  108. const
  109.     emm_int = $67;
  110.     dos_int = $21;
  111.     maxfreeblock = 4000;
  112.     xblocksize = $4000;
  113.     _get_frame = $41;
  114.     _unalloc_count = $42;
  115.     _alloc_pages = $43;
  116.     _map_page = $44;
  117.     _dealloc_pages = $45;
  118.     _change_alloc = $51;
  119. type
  120.     xheap = array[0..1000] of word;
  121.     fblock = record
  122.         page : byte;
  123.         start,stop : word;
  124.     end;
  125.     fblockarray = array[1..maxfreeblock] of fblock;
  126. var
  127.     regs : registers;
  128.     handle,tot_pages : word;
  129.     xheapptr : ^xheap;
  130.     xfreeptr : ^fblockarray;
  131.     last_page,lastptr : integer;
  132.     map : array[0..3] of integer;
  133.     frame : word;
  134.  
  135. function ems_installed : boolean;
  136. const
  137.     device_name : string[8] = 'EMMXXXX0';
  138. var
  139.     i : integer;
  140. begin
  141.     ems_installed := false;
  142.     with regs do begin  {check for ems present}
  143.         ah := $35;  {get code segment pointed to by interrupt 67h}
  144.         al := emm_int;
  145.         intr(dos_int,regs);
  146.     for i := 1 to 8 do if device_name[i] <> chr(mem[es : i + 9]) then exit;
  147.     end;
  148.     ems_installed := true;
  149. end;
  150.  
  151. function unalloc_count(var available : word): boolean;
  152. begin
  153.     with regs do begin
  154.         ah := _unalloc_count;
  155.         intr(emm_int,regs);
  156.         available := bx;
  157.         unalloc_count := ah = 0  {return the error code}
  158.     end;
  159. end;
  160.  
  161. function alloc_pages(needed: integer): boolean;
  162. begin
  163.     with regs do begin
  164.         ah := _alloc_pages;
  165.         bx := needed;
  166.         intr(emm_int,regs);
  167.         handle := dx;
  168.         alloc_pages := (ah = 0);        {return the error code}
  169.     end;
  170. end;
  171.  
  172. function xdealloc_pages: boolean;
  173. begin
  174.     with regs do begin
  175.         ah := _dealloc_pages;
  176.         dx := handle;
  177.         intr(emm_int,regs);
  178.         xdealloc_pages := (ah = 0);  {return the error code}
  179.     end;
  180. end;
  181.  
  182. function change_alloc(needed : integer) : boolean;
  183. begin
  184.     with regs do begin
  185.         ah := _change_alloc;
  186.         bx := needed;
  187.         dx := handle;
  188.         intr(emm_int,regs);
  189.         change_alloc := (ah = 0);    {return the error code}
  190.     end;
  191. end;
  192.  
  193. function xmap_page(l_page,p_page: integer): boolean;
  194. begin
  195.     xmap_page := true;
  196.     if map[p_page] <> l_page then with regs do begin
  197.         ah := _map_page;
  198.         al := p_page;
  199.         bx := l_page;
  200.         dx := handle;
  201.         intr(emm_int,regs);
  202.         xmap_page := (ah = 0);
  203.         if ah = 0 then map[p_page] := l_page;
  204.     end;
  205. end;
  206.  
  207. function xpage_in(var x : xaddress) : pointer;
  208. begin
  209.     if xmap_page(x.page,0) then xpage_in := ptr(frame,x.pos)
  210.     else xpage_in := nil;
  211. end;
  212.  
  213. function xget_frame(var frame: word): boolean;
  214. begin
  215.     with regs do begin
  216.         ah := _get_frame;
  217.         intr(emm_int,regs);
  218.         frame := bx;
  219.         xget_frame := (ah = 0); {return the error code}
  220.     end;
  221. end;
  222.  
  223. procedure xgetmem(var x : xaddress;size : word);
  224. var
  225.     i : integer;
  226. begin
  227.     for i := 1 to lastptr do begin
  228.         with xfreeptr^[i] do begin
  229.             if size <= stop - start then begin
  230.                 x.page := page;
  231.                 x.pos := start;
  232.                 inc(start,size);
  233.                 if start = stop then begin
  234.                     xfreeptr^[i] := xfreeptr^[lastptr];
  235.                     dec(lastptr);
  236.                 end;
  237.                 exit;
  238.             end;
  239.         end;
  240.     end;
  241.     x.page := nilpage;
  242.     i := 0;
  243.     repeat
  244.         inc(i);
  245.         if i > tot_pages then exit;
  246.         if i > last_page then begin
  247.             inc(last_page);
  248.             if not change_alloc(last_page) then exit;
  249.         end;
  250.     until xblocksize - xheapptr^[pred(i)] > size;
  251.     with x do begin
  252.         page := pred(i);
  253.         pos := xheapptr^[page];
  254.         inc(xheapptr^[page],size);
  255.     end;
  256. end;
  257.  
  258. procedure xfreemem(var x : xaddress;size : word);
  259. var
  260.     i,xstop : integer;
  261. begin
  262.     xstop := x.pos + size;
  263.     i := 0;
  264.     while i < lastptr do begin
  265.         inc(i);
  266.         with xfreeptr^[i] do begin
  267.             if x.page = page then begin
  268.                 if x.pos >= start then begin
  269.                     if x.pos <= stop then begin
  270.                     x.pos := start;
  271.                     if xstop < stop then xstop := stop;
  272.                     xfreeptr^[i] := xfreeptr^[lastptr];
  273.                     dec(lastptr);
  274.                     dec(i)
  275.                     end;
  276.                 end
  277.                 else if xstop >= start then begin
  278.                     if xstop < stop then xstop := stop;
  279.                     xfreeptr^[i] := xfreeptr^[lastptr];
  280.                     dec(lastptr);
  281.                     dec(i)
  282.                 end;
  283.             end;
  284.         end;
  285.     end;
  286.     if lastptr > 0 then with xfreeptr^[lastptr] do
  287.         if start = stop then dec(lastptr);
  288.     if x.pos < xstop then begin
  289.         if xstop = xheapptr^[x.page] then xheapptr^[x.page] := x.pos
  290.         else begin
  291.             if lastptr < maxfreeblock then begin
  292.                 inc(lastptr);
  293.                 with xfreeptr^[lastptr] do begin
  294.                     page := x.page;
  295.                     start := x.pos;
  296.                     stop := xstop;
  297.                 end;
  298.             end;
  299.         end;
  300.     end;
  301. end;
  302.  
  303. function xmemavail : longint;
  304. var
  305.     s : longint;
  306.     i : integer;
  307. begin
  308.     s := 0;
  309.     for i := 0 to pred(tot_pages) do inc(s,$4000 - xheapptr^[i]);
  310.     for i := 1 to lastptr do with xfreeptr^[i] do inc(s,stop - start);
  311.     xmemavail := s;
  312. end;
  313.  
  314. function xmaxavail : longint;
  315. var
  316.     s : longint;
  317.     i : integer;
  318. begin
  319.     s := 0;
  320.     for i := 0 to pred(tot_pages) do
  321.         if $4000 - xheapptr^[i] > s then s := $4000 - xheapptr^[i];
  322.     for i := 1 to lastptr do with xfreeptr^[i] do
  323.         if stop - start > s then s := stop - start;
  324.     xmaxavail := s;
  325. end;
  326.  
  327. procedure xalloc_done;
  328. begin
  329.     if not xdealloc_pages then;
  330. end;
  331.  
  332. function xalloc_init : boolean;
  333. var
  334.     i : word;
  335. begin
  336.     xalloc_init := false;
  337.     if not ems_installed then exit;
  338.     if not unalloc_count(tot_pages) then exit;
  339.     if tot_pages = 0 then exit;
  340.     if not xget_frame(frame) then exit;
  341.     getmem(xheapptr,tot_pages*sizeof(word));
  342.     if xheapptr = nil then exit;
  343.     new(xfreeptr);
  344.     if xfreeptr = nil then exit;
  345.     for i := 0 to pred(tot_pages) do xheapptr^[i] := 0;
  346.     if not alloc_pages(1) then exit;
  347.     xalloc_init := true;
  348.     lastptr := 0;
  349.     last_page := 1;
  350.     for i := 0 to 3 do map[i] := -1;
  351. end;
  352.  
  353. end.
  354.